\section{Código}

\subsection{script.py}
\begin{verbatim}
# -*- coding: utf8 -*-
from scapy.all import *
from auxiliares import * 
import time


def arping(dst_ip):
    is_alive = response = None
    timeout = 5 # segundos
    a = ARP()
    a.pdst = dst_ip #la ip de la cual estamos averiguando su MAC
    a.hwdst = 'ff:ff:ff:ff:ff:ff' # el paquete se envia a todos
    response = sr1(a, timeout=timeout)
    is_alive = response is not None
    return is_alive, response


def icmping(dst_ip):
    return icmping_con_ttl_y_timeout(dst_ip)
    

def icmping_con_ttl_y_timeout(dst_ip, ttl=None, timeout=5):
    is_alive = response = None
    i = ICMP()
    p = IP(dst=dst_ip) / i / 'tp de redes'
    if ttl is not None:
        p.ttl = ttl
    response = sr1(p, timeout=timeout)
    is_alive = response is not None

    return (is_alive, response)


def arp_discovery(rango):
    rango_separado = rango.split("/")
    dir_ip = rango_separado[0]
    mascara = int(rango_separado[1])
    cantidad_de_bits_para_direcciones = 32 - mascara
    cantidad_de_direcciones = pow(2, cantidad_de_bits_para_direcciones)
    dir_de_red = dir_ip_de_red(dir_ip, mascara)
    return arp_discovery_aux(dir_de_red, cantidad_de_direcciones)

def arp_discovery_aux(ip_inicial, cantidad_direcciones):
    discovered = []
    ip_actual = ip_inicial
    while ip_actual is not None and cantidad_direcciones > 0:
        is_alive = arping(ip_actual)[0]
        discovered.append((is_alive, ip_actual))
        ip_actual = siguiente_ip(ip_actual)
        cantidad_direcciones = cantidad_direcciones - 1
    return discovered


def icmp_discovery(rango):
    rango_separado = rango.split("/")
    dir_ip = rango_separado[0]
    mascara = int(rango_separado[1])
    cantidad_de_bits_para_direcciones = 32 - mascara
    cantidad_de_direcciones = pow(2, cantidad_de_bits_para_direcciones)
    dir_de_red = dir_ip_de_red(dir_ip, mascara)
    return icmp_discovery_aux(dir_de_red, cantidad_de_direcciones)


def icmp_discovery_aux(ip_inicial, cantidad_de_direcciones):
    discovered = []
    ip_actual = ip_inicial
    while ip_actual is not None and cantidad_de_direcciones > 0:
        is_alive = icmping(ip_actual)[0]
        discovered.append((is_alive, ip_actual))
        ip_actual = siguiente_ip(ip_actual)
        cantidad_de_direcciones = cantidad_de_direcciones - 1
    return discovered


def traceroute(dst_ip, timeout = 5):
    route = [] # lista de (dir ip, distancia a dst_ip)

    for ttl in range(1, 30): 
        resultado = icmping_con_ttl_y_timeout(dst_ip, ttl, timeout)
        is_alive = resultado[0]
        if is_alive:
            response = resultado[1]
            if response['ICMP'].type == 11:  # time-exceeded
                route.append((response.src, ttl))
            else:
                route.append(('*', ttl))
        else:
            route.append((None, ttl))

    return route


 
\end{verbatim}


\newpage
\subsection{auxiliares.py}

\begin{verbatim}
# -*- coding: utf8 -*-

def completar_a_ocho_bits(binario):
    bits_del_binario = len(binario) - 2
    bits_que_faltan = 8 - bits_del_binario
    binario_en_ocho = str(binario).split("b")[1]
    while bits_que_faltan > 0:
        binario_en_ocho = '0' + binario_en_ocho
        bits_que_faltan = bits_que_faltan - 1
    return binario_en_ocho

def ip_en_binario(ip):
    values = ip.split(".")
    byte1 = completar_a_ocho_bits(str(bin(int(values[0]))))
    byte2 = completar_a_ocho_bits(str(bin(int(values[1]))))
    byte3 = completar_a_ocho_bits(str(bin(int(values[2]))))
    byte4 = completar_a_ocho_bits(str(bin(int(values[3]))))
    return [list(byte1), list(byte2), list(byte3), list(byte4)]

def dir_ip_de_red(ip, mascara):
    ip_binaria = ip_en_binario(ip)
    i = 0
    j = 0
    while i < 32:
        if j > 7:
            j = 0
        if i >= mascara:
            ip_binaria[i/8][j] = '0'
        i = i + 1
        j = j + 1
    ip_con_mascara = []
    ip_con_mascara.append(str(int(''.join(ip_binaria[0]), 2)))
    ip_con_mascara.append(str(int(''.join(ip_binaria[1]), 2)))
    ip_con_mascara.append(str(int(''.join(ip_binaria[2]), 2)))
    ip_con_mascara.append(str(int(''.join(ip_binaria[3]), 2)))
    return '.'.join(ip_con_mascara)

def siguiente_ip(ip):
    values = ip.split(".")
    primer_byte = int(values[0])
    segundo_byte = int(values[1])
    tercer_byte = int(values[2])
    cuarto_byte = int(values[3])

    primer_byte_sig = primer_byte
    segundo_byte_sig = segundo_byte
    tercer_byte_sig = tercer_byte
    cuarto_byte_sig = cuarto_byte + 1

    if cuarto_byte == 255:
        cuarto_byte_sig = 0
        if tercer_byte == 255:
            tercer_byte_sig = 0 
            if segundo_byte == 255:
                segundo_byte_sig = 0
                if primer_byte == 255:
                    return None
                else:
                    primer_byte_sig = primer_byte + 1
            else:
                segundo_byte_sig = segundo_byte + 1
        else:
            tercer_byte_sig = tercer_byte + 1

    sig_ip = str(primer_byte_sig) + '.'
    sig_ip = sig_ip + str(segundo_byte_sig) + '.'
    sig_ip = sig_ip + str(tercer_byte_sig) + '.'
    sig_ip = sig_ip + str(cuarto_byte_sig)
    return sig_ip
 
\end{verbatim}
